#include <testssisensorbi/TestSSISensorBiE.h>

// ***********************************************************************

// class EDROOMTopContext

// ***********************************************************************



	// CONSTRUCTORES***********************************************

TestSSISensorBi::EDROOMTopContext::EDROOMTopContext (TestSSISensorBi &act, int & EDROOMpVarVMessageNumber, int & EDROOMpVarVMessageReceived, bool_t & EDROOMpVarVMoreData, CDFrame & EDROOMpVarVDataFrame, CEDROOMPOOLCDFrame & EDROOMpPoolCDFrame, CEDROOMPOOLCDSignal & EDROOMpPoolCDSignal ):

	EDROOMcomponent(act)
	,Msg(EDROOMcomponent.Msg)
	,MsgBack(EDROOMcomponent.MsgBack)
	,SsiCtrl(EDROOMcomponent.SsiCtrl)
	,StoreAndNextFrame(EDROOMcomponent.StoreAndNextFrame)
	, VMessageNumber ( EDROOMpVarVMessageNumber )
	, VMessageReceived ( EDROOMpVarVMessageReceived )
	, VMoreData ( EDROOMpVarVMoreData )
	, VDataFrame ( EDROOMpVarVDataFrame )
	, CEDROOMPoolCDFrame ( EDROOMpPoolCDFrame )
	, EDROOMPoolCDSignal ( EDROOMpPoolCDSignal )
 {

}

TestSSISensorBi::EDROOMTopContext::EDROOMTopContext ( EDROOMTopContext &contex ):

	EDROOMcomponent(contex.EDROOMcomponent),
	Msg(contex.Msg),
	MsgBack(contex.MsgBack)
	,SsiCtrl(contex.SsiCtrl)
	,StoreAndNextFrame(contex.StoreAndNextFrame)
	, VMessageNumber ( contex.VMessageNumber )
	, VMessageReceived ( contex.VMessageReceived )
	, VMoreData ( contex.VMoreData )
	, VDataFrame ( contex.VDataFrame )
	, CEDROOMPoolCDFrame ( contex.CEDROOMPoolCDFrame )
	, EDROOMPoolCDSignal ( contex.EDROOMPoolCDSignal )
 {

}

	// EDROOMSearchContextTrans********************************************

bool TestSSISensorBi::EDROOMTopContext::EDROOMSearchContextTrans(TEDROOMTransId &edroomCurrentTrans){

	bool edroomValidMsg=false; 

	 switch(Msg->signal){

		 case ( EDROOMSignalDestroy ): 

			 edroomValidMsg=true;
			 edroomCurrentTrans.distanceToContext = 0 ;
			 edroomCurrentTrans.localId = -1 ;
			 break;

	}

	return(edroomValidMsg);

}

	// Funciones Definidas por el usuario  ****************************

bool_t	TestSSISensorBi::EDROOMTopContext::FGetFrames(TEDROOMInt32 numFile,byte_t *message)

{
	FILE *fich;
	char rute[50];
	byte_t aux[10];
 
	strcpy(rute,"DwFrames/");
	FIntToChar(numFile,aux);
	strcat(rute,(char *)aux);
	fich=fopen(rute,"rb");    
	if (fich==NULL)
	{
		return false;
	}
	else
	{
		 fread(message,1,50,fich);
		 fclose(fich);
 	}
	return true;
 
 
}



void	TestSSISensorBi::EDROOMTopContext::FInit()

{
	// send new Msg
	SsiCtrl.send(SToListening, EDROOMprioNormal);
 
}



void	TestSSISensorBi::EDROOMTopContext::FIntToChar(TEDROOMInt32 num,byte_t * cConvert)

{
 
	byte_t aux;
	TEDROOMInt32 i=0;
	TEDROOMInt32 j;
	do
	{ 
		cConvert[i++]= (num % 10) + '0';
		num=num/10;
	}
	while (num>0);
	cConvert[i--]='\0';
	j=0;
	for (;i>j;i--,j++)
	{
		aux=cConvert[i];
		cConvert[i]=cConvert[j];
		cConvert[j]=aux;
 
	}
 
}



void	TestSSISensorBi::EDROOMTopContext::FSendNextData()

{
	CDFrame * ap_CDFrame = CEDROOMPoolCDFrame.AllocData();
	*ap_CDFrame=VDataFrame;
	StoreAndNextFrame.send(SDataFrame, EDROOMprioNormal, ap_CDFrame, &CEDROOMPoolCDFrame);
	VMessageNumber++;	
}



void	TestSSISensorBi::EDROOMTopContext::FStoreFrame()

{
	CDFrame & varCDFrame = *(CDFrame *)Msg->data; 
	FILE *fich;
	byte_t data[32];
	TEDROOMInt32 length;
 
	fich=fopen("FUpFrames.jpg","ab");
	ssi_link_layer_get_data(varCDFrame.dataFrame,data);
	length = ssi_link_layer_get_data_length(varCDFrame.dataFrame);
 
	if (fich != NULL)
	{				
		fwrite(data, 1,length, fich);
		fclose(fich);
	}

	if (VMessageReceived==1559)
	{
	   FCheckFiles();
	   exit(0);
 	}
 	VMessageReceived++;
 
 
}


void	TestSSISensorBi::EDROOMTopContext::FCheckFiles()

{
	printf("TEST : CHECK\n");
	FILE *originFile,*finalFile;
	bool_t ok=true;
	byte_t originBuffer[50], finalBuffer[50];

   finalFile=fopen("FUpFrames.jpg","rb");
   originFile=fopen("OUpFrames.jpg","rb");
   if (finalFile!=NULL && originFile!=NULL)
   {
     do
		{
		   for (TEDROOMInt32 i =0; i< 50; i++)
		   {
			   originBuffer[i]=0;
			   finalBuffer[i]=0;
		   }
		   fread(originBuffer, 1,1, originFile);
		   fread(finalBuffer, 1,1, finalFile);
		   if(originBuffer[0]!=finalBuffer[0])
		   {
			ok=false;
		   }
		} while (!feof(originFile) && !feof(finalFile));
	   fclose(originFile);
	   fclose(finalFile);
   }
   else
   {
	   ok=false;
	   if (finalFile!=NULL)
	   {
		   fclose(finalFile);
	   }
	   if (originFile!=NULL)
	   {
		   fclose(originFile);
	   }
   }

   if (ok)
   {
   	printf("TEST UP FRAMES: OK\n");
   }
   else
   {
   	printf("TEST UP FRAMES: ERROR\n");
   }
}




void	TestSSISensorBi::EDROOMTopContext::FStoreAck()

{
	//TODO: gestionar los acks recibidos que confirman los datos enviados 
	// descendentemente
}



void	TestSSISensorBi::EDROOMTopContext::FReceiveNextSignal()

{
	// send new Msg
	VMoreData=FGetFrames(VMessageNumber,VDataFrame.dataFrame);

}



bool_t	TestSSISensorBi::EDROOMTopContext::GMoreData()

{
 return (VMoreData);
}



void	TestSSISensorBi::EDROOMTopContext::FSendAck()

{
	byte_t radioIdAux[6];
	CDSignal * ap_CDSignal = EDROOMPoolCDSignal.AllocData();
	byte_t finalFrame[17];

		int8_t i=0;
		struct ssi_link_layer_signal_frame_info_t ackFrame;
		strcpy((char*)ackFrame.radio_id,"000001");
		ackFrame.sensor_id=MASK_BIDIRECTIONAL_SSI;
		ackFrame.flags=MASK_ACK_SSI;
		strcpy((char*)ackFrame.reserved,"000000");

		ssi_link_layer_build_signal_frame(finalFrame,&ackFrame);

		for (i=0;i<17;i++)
		{
			ap_CDSignal->signalFrame[i]=finalFrame[i];
		}

	// Complete Data
	//build_ack(ap_CDSignal->signalFrame,radioIdAux,MASK_BIDIRECTIONAL_SSI);
	// send new Msg
	StoreAndNextFrame.send(SSignalFrame, EDROOMprioNormal, ap_CDSignal, &EDROOMPoolCDSignal);
 
 


}



	//*****Pools

	//CEDROOMPOOLCDFrame

TestSSISensorBi::EDROOMTopContext::CEDROOMPOOLCDFrame::CEDROOMPOOLCDFrame(unsigned int elemCount, CDFrame* pMem, bool_t * pMemMarks):CEDROOMProtectedMemoryPool(elemCount, pMem, pMemMarks, sizeof (CDFrame)){;}

CDFrame *	TestSSISensorBi::EDROOMTopContext::CEDROOMPOOLCDFrame::AllocData(){
	return(CDFrame*)CEDROOMProtectedMemoryPool::AllocData();
}

	//CEDROOMPOOLCDSignal

TestSSISensorBi::EDROOMTopContext::CEDROOMPOOLCDSignal::CEDROOMPOOLCDSignal(unsigned int elemCount, CDSignal* pMem, bool_t * pMemMarks):CEDROOMProtectedMemoryPool(elemCount, pMem, pMemMarks, sizeof (CDSignal)){;}

CDSignal *	TestSSISensorBi::EDROOMTopContext::CEDROOMPOOLCDSignal::AllocData(){
	return(CDSignal*)CEDROOMProtectedMemoryPool::AllocData();
}



// ***********************************************************************

// class EDROOMTopState

// ***********************************************************************



	// CONSTRUCTOR*************************************************

TestSSISensorBi::EDROOMTopState::EDROOMTopState (TestSSISensorBi &act, CEDROOMMemory *pEDROOMMemory  ):
	  EDROOMTopContext( act , VMessageNumber, VMessageReceived, VMoreData, VDataFrame,CEDROOMPoolCDFrame,EDROOMPoolCDSignal )
	, VMessageNumber ( 1 )
	, VMessageReceived ( 1 )
	, VMoreData ( false )
	, CEDROOMPoolCDFrame ( 10, pEDROOMMemory->poolCDFrame, pEDROOMMemory->poolMarkCDFrame)
	, EDROOMPoolCDSignal ( 10, pEDROOMMemory->poolCDSignal, pEDROOMMemory->poolMarkCDSignal)
{

}

	// EDROOMBehaviour**********************************************

void TestSSISensorBi::EDROOMTopState::EDROOMBehaviour(){

	TEDROOMTransId edroomCurrentTrans;

	edroomCurrentTrans = EDROOMIllegada();

	do{

		switch(edroomCurrentTrans.localId){

			case(Init):
				FInit();
				edroomNextState = Listening;
				break;
			case(StoreFrame):
				FStoreFrame();
				edroomNextState = Listening;
				break;
			case(ReceiveAck):
				FStoreAck();
				edroomNextState = Listening;
				break;
			case(ReceiveNextSignal):
				FReceiveNextSignal();

				EDROOMcomponent.EDROOMTraceStateEntry();

				if( GMoreData() ){
					FSendNextData();
					edroomCurrentTrans.localId = ReceiveNextSignal_SendData;
					edroomNextState = Listening;
				 } 
				else{
					FSendAck();
					edroomCurrentTrans.localId = ReceiveNextSignal_SendAck;
					edroomNextState = Listening;
				 } 
				EDROOMcomponent.EDROOMTraceTrans(edroomCurrentTrans, Msg->signal);
				break;
		}

		EDROOMcomponent.EDROOMTraceStateEntry();

		EDROOMcomponent.EDROOMTraceStateEntry();

		switch(edroomNextState){

			case(I):
				edroomCurrentTrans=EDROOMIllegada();
				break;

			case(Listening):
				edroomCurrentTrans=EDROOMListeningllegada();
				break;

		}

		EDROOMcomponent.EDROOMTraceStateExit();

		edroomCurrentState=edroomNextState;

	}while(Msg->signal != EDROOMSignalDestroy);

}



	// Inicio**********************************************

void TestSSISensorBi::EDROOMTopState::EDROOMInicio(){

edroomCurrentState=I;

}



//	 ***********************************************************************

//	 llegada SubEstado I

//	 ***********************************************************************



TEDROOMTransId TestSSISensorBi::EDROOMTopState::EDROOMIllegada(){

	TEDROOMTransId edroomCurrentTrans;

	edroomCurrentTrans.localId = Init;
	edroomCurrentTrans.distanceToContext = 0;
	EDROOMcomponent.EDROOMTraceTrans(edroomCurrentTrans, 0);

	return(edroomCurrentTrans);

}



	// ***********************************************************************

	// llegada SubEstado Hoja Listening

	// ***********************************************************************



TEDROOMTransId TestSSISensorBi::EDROOMTopState::EDROOMListeningllegada(){

	TEDROOMTransId edroomCurrentTrans;

	int edroomValidMsg=false;

	do{

		EDROOMNuevoMens ();

		switch(Msg->signal){

			case (SDataFrame): 

				 if ( *Msg->GetPInterface() == StoreAndNextFrame) {

					edroomCurrentTrans.localId= StoreFrame;
					edroomCurrentTrans.distanceToContext = 0;
					edroomValidMsg=true;
				 }

				break;

			case (SSignalFrame): 

				 if ( *Msg->GetPInterface() == StoreAndNextFrame) {

					edroomCurrentTrans.localId= ReceiveAck;
					edroomCurrentTrans.distanceToContext = 0;
					edroomValidMsg=true;
				 }

				break;

			case (SNextSensorSsiDataFrame): 

				 if ( *Msg->GetPInterface() == StoreAndNextFrame) {

					edroomCurrentTrans.localId = ReceiveNextSignal;
					edroomCurrentTrans.distanceToContext = 0 ;
					edroomValidMsg=true;
				 }

				break;

		};

		if (!edroomValidMsg) edroomValidMsg = EDROOMSearchContextTrans(edroomCurrentTrans);

	} while (!edroomValidMsg);

	EDROOMcomponent.EDROOMTraceTrans(edroomCurrentTrans, Msg->signal);

	return(edroomCurrentTrans);

}



